import fg from "fast-glob";
import fs from "fs-extra";
import path from "path";
import { BaseTask, TaskResult } from "../../common/tasks/BastTask.js";
import { toolchain } from '../../toolchain.js';
import { Cmd, ExecuteError } from '../../tools/Cmd.js';
import { EErrorType } from "../../LogParser.js";
import { EFileErrorType, alertErrorFile, sendBuildFailureAlert } from "../../tools/alert.js";

/**Unity编译ts */
export class UnityTscTask extends BaseTask<void> {
    async run(): Promise<TaskResult<void>> {
        // 如果项目中存在tsbuild.py则不执行本步骤，沿用老的做法，在构AB包时编译脚本
        const oldBuildPy = path.join(toolchain.params.workSpacePath, 'Assets/Editor/tools/tsbuild.py');
        if (fs.existsSync(oldBuildPy)) {
            return { success: true, errorCode: 0, data: void 0 };
        }

        // 动态修改copytasks
        const fysdk = toolchain.params.channelCfg['fysdk-libs'];
        if (fysdk) {
            const ctj = path.join(toolchain.params.workSpacePath, 'build-tools/cfg/copytasks.json');
            if (fs.existsSync(ctj)) {
                const cfjContent = await fs.readFile(ctj, 'utf-8');
                await fs.writeFile(ctj, cfjContent.replace(/(?<=libs\/)cjs/g, fysdk), 'utf-8');
            }
        }

        const tsSource = path.join(toolchain.params.workSpacePath, 'TsScripts');
        const tsOutput = path.join(toolchain.params.workSpacePath, 'TsScripts/.dist');
        // 先清空TsScripts/.dist
        if (fs.existsSync(tsOutput)) await fs.emptyDir(tsOutput);
        // 开始编译ts
        process.chdir(tsSource);
        const cmd = new Cmd();
        let catchError = 0;
        let errorCode = await cmd.runNodeModule('npm', ['run', 'build']).catch((e: ExecuteError) => {
            catchError = e.code;
        });
        if (catchError != 0) errorCode = catchError;
        if (errorCode != 0) {
            console.error('typescript compile failed: ' + errorCode);
            toolchain.logParser.parseUnityBuildLog(cmd.output, errorCode || 0);
            if(toolchain.logParser.error) {
                if (toolchain.logParser.isKindOf(EErrorType.CompilationFailed)) {
                    const errorFiles = toolchain.logParser.errorFiles;
                    await alertErrorFile(errorFiles[0].file, EFileErrorType.CodeError, toolchain.logParser.error);
                }
                await sendBuildFailureAlert(toolchain.logParser.error, true, false);
            }
            process.exit(1);
        }
        // 拷贝到bytes
        const bytesRoot = path.join(toolchain.params.workSpacePath, 'Assets/AssetSources/tsbytes');
        // 先清空bytes文件
        const bytesFiles = await fg(['**/*.bytes', '**/*.json'], { cwd: bytesRoot });
        for (const bf of bytesFiles) {
            fs.unlink(path.join(bytesRoot, bf));
        }
        // 开始拷贝
        const csrcFiles = await fg(['**/*.js', '**/*.cjs', '**/*.mjs', '**/*.json'], { cwd: tsOutput });
        for (const cf of csrcFiles) {
            let tfn: string;
            if (cf.endsWith('.json')) {
                tfn = cf;
            } else {
                tfn = path.join(path.dirname(cf), path.basename(cf, path.extname(cf)) + '.bytes');
            }
            const tf = path.join(bytesRoot, tfn);
            await fs.ensureDir(path.dirname(tf));
            await fs.copyFile(path.join(tsOutput, cf), tf);
        }
        return { success: true, errorCode: 0, data: void 0 };
    }
}
